package com.dingreading.cloud.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.aliyun.AliyunMessageUtils;
import com.dingreading.cloud.common.util.excel.ExcelHandler;
import com.dingreading.cloud.common.util.wechat.PayExtraUtil;
import com.dingreading.cloud.common.util.wechat.WxPayBusiness;
import com.dingreading.cloud.web.dto.TicketUserVO;
import com.dingreading.cloud.web.entity.MsgSends;
import com.dingreading.cloud.web.entity.NjTicketOrder;
import com.dingreading.cloud.web.entity.NjTicketUser;
import com.dingreading.cloud.web.entity.WxAcecGzhUser;
import com.dingreading.cloud.web.service.*;
import com.dingreading.cloud.web.util.MsgTask;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RefreshScope
@RestController
@RequestMapping("/front/ticketUser")
@Api(tags = "ACEC门票用户管理")
public class TicketUserController {

    @Value("${wx.nj.appId}")
    private String njAppId;
    @Value("${wx.nj.appSecret}")
    private String njAppSecret;
    @Value("${wx.nj.mchId}")
    private String njMchId;
    @Value("${wx.nj.mchKey}")
    private String njMchKey;
    @Value("${aliYun.sms.accessKeyId}")
    private String accessKeyId;
    @Value("${aliYun.sms.accessKeySecret}")
    private String accessKeySecret;
    // 支付回调地址
    @Value("${payNotifyUrl}")
    private String notifyUrl;

    @Resource
    private NjTicketUserService ticketUserService;
    @Resource
    private NjTicketOrderService ticketOrderService;
    @Resource
    private WxAcecGzhUserService acecGzhUserService;
    @Resource
    private NjTicketSellerService ticketSellerService;
    @Resource
    private MsgSendsService msgSendsService;

    @Resource
    private MsgTask msgTask;


    @ApiOperation(value = "根据微信用户id获取门票用户信息")
    @PostMapping(value = "/getTicketUser")
    public R<Object> getTicketUser(
            @ApiParam(value = "微信用户id") @RequestParam(value = "openid") String openid
    ) {
        if (StringUtils.isBlank(openid))
            return R.fail("请在微信内打开领票页面");

        String year = String.valueOf(DateUtil.getYear());

        List<NjTicketUser> users = ticketUserService.getByOpenid(openid, year);
        if (CollectionUtils.isNotEmpty(users)) {
            NjTicketUser user = users.get(0);
            JSONObject jsonObject = JsonUtil.toJsonObject(user);
            int subscribe = 0;
            List<WxAcecGzhUser> gzhUserList = acecGzhUserService.getByOpenid(openid);
            if (CollectionUtils.isNotEmpty(gzhUserList)) {
                WxAcecGzhUser wxAcecGzhUser = gzhUserList.get(0);
                subscribe = wxAcecGzhUser.getSubscribe();
            }
            jsonObject.put("subscribe", subscribe);
            return R.ok(jsonObject);
        }
        return R.ok();
    }

    @ApiOperation(value = "通过手机号和微信用户id获取门票用户信息")
    @PostMapping(value = "/getUserByPhone")
    public R<Object> getUserByPhone(
            @ApiParam(value = "微信用户id") @RequestParam(value = "openid") String openid,
            @ApiParam(value = "手机号") @RequestParam(value = "phone") String phone
    ) {
        if (StringUtils.isBlank(openid))
            return R.fail("请在微信内打开领票页面");

        String year = String.valueOf(DateUtil.getYear());

        List<NjTicketUser> users = ticketUserService.getByPhone(phone, year);
        if (CollectionUtils.isNotEmpty(users)) {
            NjTicketUser user = users.get(0);
            JSONObject jsonObject = JsonUtil.toJsonObject(user);
            int subscribe = 0;
            List<WxAcecGzhUser> gzhUserList = acecGzhUserService.getByOpenid(openid);
            if (CollectionUtils.isNotEmpty(gzhUserList)) {
                WxAcecGzhUser wxAcecGzhUser = gzhUserList.get(0);
                subscribe = wxAcecGzhUser.getSubscribe();
            }
            jsonObject.put("subscribe", subscribe);
            return R.ok(jsonObject);
        }
        return R.ok();
    }

    @ApiOperation(value = "保存领票用户信息")
    @PostMapping(value = "/createTicketUser")
    public R<Object> createTicketUser(
            @ApiParam(value = "手机号") @RequestParam(value = "phone") String phone,
            @ApiParam(value = "用户姓名") @RequestParam(value = "name") String name,
            @ApiParam(value = "机构名称") @RequestParam(value = "corpName") String corpName,
            @ApiParam(value = "微信用户id") @RequestParam(value = "openid") String openid,
            @ApiParam(value = "参与类型 1.观展票 2.展位预订") @RequestParam(value = "joinType") Integer joinType,
            @ApiParam(value = "渠道") @RequestParam(value = "from") String from
    ) {
        if (StringUtils.isBlank(openid))
            return R.fail("请在微信内打开领票页面");
        if (StringUtils.isBlank(phone) || phone.length() != 11)
            return R.fail("请填写正确的手机号");
        if (StringUtils.isBlank(name))
            return R.fail("请填写用户姓名");
        if (joinType == null || (!joinType.equals(1) && !joinType.equals(2)))
            return R.fail("门票类型错误");
        // 如果渠道不存则从公众号用户来源获取渠道
        if (StringUtils.isBlank(from) || from.equals("0")) {
            List<WxAcecGzhUser> gzhUserList = acecGzhUserService.getByOpenid(openid);
            if (CollectionUtils.isNotEmpty(gzhUserList)) {
                from = gzhUserList.get(0).getSource();
            }
        }

        String year = String.valueOf(DateUtil.getYear());

        if (joinType.equals(1)) {
            List<NjTicketUser> openIdList = ticketUserService.getByOpenid(openid, year);
            if (CollectionUtils.isNotEmpty(openIdList)) {
                NjTicketUser ticketUser = openIdList.get(0);
                if (ticketUser.getGetStatus().equals(1))
                    return R.fail("该微信号已领取过门票");
            }

            List<NjTicketUser> users = ticketUserService.getByPhone(phone, year);
            NjTicketUser data = null;
            if (CollectionUtils.isNotEmpty(users)) {
                data = users.get(0);
                // 免费票领取状态
                if (data.getGetStatus().equals(1)) {
                    // 如果是抖音导入的观展票用户，则绑定微信openid
                    if (StringUtils.isBlank(data.getOpenid())) {
                        data.setOpenid(openid);
                        ticketUserService.saveOrUpdate(data);
                    }
                    return R.fail("该手机号已领取过门票");
                }
            } else {
                data = new NjTicketUser();
                data.setYear(year);
                data.setUid(KitUtil.getUuid());
                // 门票类型 0.未领票 1.参会票 2.观展票
                data.setTicketType(2);
                data.setTicketTypeName("观展票");
                data.setUserType("观展人员");
                data.setGetStatus(0);
                data.setGetStatusName("未领票");
                data.setPermitStatus(0);
                data.setPermitStatusName("未领取");
                data.setPermitNum(0);
                data.setPaymentStatus(0);
                data.setPaymentStatusName("未付款");
            }
            data.setCorpName(NepUtil.nullToZero(corpName));
            data.setPhone(phone);
            data.setName(name);
            data.setOpenid(openid);
            data.setFrom(from);
            ticketUserService.saveOrUpdate(data);
        } else {
            // 展位预订
//            NjBookUser bookUser = null;
//            List<NjBookUser> list = bookUserService.getByPhone(phone);
//            if (CollectionUtils.isNotEmpty(list)) {
//                bookUser = list.get(0);
//            } else {
//                bookUser = new NjBookUser();
//                bookUser.setYear("2024");
//            }
//            bookUser.setCorpName(NepUtil.nullToZero(corpName));
//            bookUser.setPhone(phone);
//            bookUser.setName(name);
//            bookUser.setOpenid(openid);
//            bookUserService.saveOrUpdate(bookUser);
            return R.fail("您的信息已提交，稍后将有工作人员与您联系");
        }
        return R.ok();
    }

    @ApiOperation(value = "统计已领票和未领票的用户数量")
    @PostMapping(value = "/getTicketUserNum")
    public R<Object> getTicketUserNum(
    ) {
        JSONObject jsonObject = ticketUserService.getGetStatusCnt();

        return R.ok(jsonObject);
    }

    @ApiOperation(value = "获取短信验证码")
    @PostMapping(value = "/getMsgCode")
    public R<Object> getMsgCode(
            @ApiParam(value = "手机号码") @RequestParam(value = "phone") String phone
    ) throws Exception {
        if (StringUtils.isBlank(phone) || phone.length() != 11)
            return R.fail("请填写正确的手机号");

        String year = String.valueOf(DateUtil.getYear());

        List<NjTicketUser> list = ticketUserService.getByPhone(phone, year);
        if (CollectionUtils.isEmpty(list))
            return R.fail("未发现手机号注册的用户");
        NjTicketUser user = list.get(0);
        if (user.getGetStatus().equals(1))
            return R.fail("该手机号已领取过门票");

        String code = KitUtil.getRandomNum(4);
        // 发送短信
        String send = AliyunMessageUtils.acecSendVerifyCode(accessKeyId, accessKeySecret, phone, code);

        if (StringUtils.isBlank(send))
            return R.fail("短信发送失败");
        JSONObject jsonObject = JSONObject.parseObject(send);
        String sendCode = jsonObject.getString("Code");
        String Message = jsonObject.getString("Message");
        if (null == sendCode || !sendCode.equals("OK")) {
            return R.fail(Message);
        }

        Date time = DateUtil.getNowDatetime();
        Date expireTime = DateUtil.addMinutes(time, 15);
        MsgSends data = new MsgSends();
        data.setCorpName("阿里云");
        data.setPhone(phone);
        data.setCode(code);
        data.setExpireTime(expireTime);
        msgSendsService.saveOrUpdate(data);

        return R.ok(code);
    }

    @ApiOperation(value = "验证短信并领取展会门票")
    @PostMapping(value = "/getExhibitionTicket")
    public R<Object> getExhibitionTicket(
            @ApiParam(value = "微信用户id") @RequestParam(value = "openid") String openid,
            @ApiParam(value = "手机号") @RequestParam(value = "phone") String phone,
            @ApiParam(value = "短信验证码") @RequestParam(value = "msgCode") String msgCode
    ) {
        if (StringUtils.isBlank(msgCode))
            return R.fail("请填写短信验证码");

        String year = String.valueOf(DateUtil.getYear());
        Date nowTime = DateUtil.getNowDatetime();

        // 验证短信验证码
        List<MsgSends> msgSendsList = msgSendsService.getByPhoneAndCode(phone, msgCode);
        if (CollectionUtils.isEmpty(msgSendsList))
            return R.fail("验证码错误");
        MsgSends msgSends = msgSendsList.get(0);
        Date expireTime = msgSends.getExpireTime();
        if (nowTime.getTime() > expireTime.getTime())
            return R.fail("验证码已过期");

        NjTicketUser data = null;
        List<NjTicketUser> list = ticketUserService.getByPhone(phone, year);
        if (CollectionUtils.isEmpty(list))
            return R.fail("未发现手机号注册的用户");
        data = list.get(0);
        if (data.getGetStatus().equals(1)) {
            return R.fail("该手机号已领取过门票");
        }

        // 门票类型 1.参会票 2.观展票
        // 用户类型 观展人员 工作人员 媒体 展商 嘉宾
//        List<NjExhibitor> exhibitors = exhibitorService.getByPhone(phone);
//        if (CollectionUtils.isNotEmpty(exhibitors)) {
//            // 如果是参展用户，则门票改为参会票
//            data.setTicketType(1);
//            data.setTicketTypeName("参会票");
//            data.setUserType("展商");
//        }
        data.setOpenid(openid);
        // 设置已领票
        data.setGetStatus(1);
        data.setGetStatusName("已领票");
        ticketUserService.saveOrUpdate(data);

        return R.ok();
    }

    @ApiOperation(value = "观展票付钱升级参会票")
    @PostMapping(value = "/payTicket")
    public R<Object> payTicket(
            HttpServletRequest request,
            @ApiParam(value = "微信用户id") @RequestParam(value = "openid") String openid,
            @ApiParam(value = "手机号") @RequestParam(value = "phone") String phone,
            @ApiParam(value = "付款金额") @RequestParam(value = "payAmount") String payAmount,
            @ApiParam(value = "渠道") @RequestParam(value = "from") String from
    ) throws Exception {
        if (StringUtils.isBlank(phone) || phone.length() != 11)
            return R.fail("手机号码错误");
        if (StringUtils.isBlank(payAmount))
            return R.fail("付款金额错误");
        double amount = Double.parseDouble(payAmount);
        if (amount <= 0)
            return R.fail("付款金额必须大于0");
        // 如果渠道不存则从公众号用户来源获取渠道
        if (StringUtils.isBlank(from) || from.equals("0")) {
            List<WxAcecGzhUser> gzhUserList = acecGzhUserService.getByOpenid(openid);
            if (CollectionUtils.isNotEmpty(gzhUserList)) {
                from = gzhUserList.get(0).getSource();
            }
        }

        String year = String.valueOf(DateUtil.getYear());
        List<NjTicketUser> userList = ticketUserService.getByPhone(phone, year);
        if (CollectionUtils.isEmpty(userList))
            return R.fail("用户信息未查询到");

        NjTicketUser ticketUser = userList.get(0);
        if (ticketUser.getTicketType().equals(1))
            return R.fail("用户的门票已是参会票");
        if (null != ticketUser.getPaymentStatus() && ticketUser.getPaymentStatus().equals(1))
            return R.fail("用户的参会票已付款，不能重复操作");

        NjTicketOrder ticketOrder = new NjTicketOrder();
        ticketOrder.setYear(year);
        ticketOrder.setOrderCode(KitUtil.getNjCode());
        ticketOrder.setUserUid(ticketUser.getUid());
        ticketOrder.setUserPhone(ticketUser.getPhone());
        ticketOrder.setUserName(ticketUser.getName());
        ticketOrder.setCorpName(ticketUser.getCorpName());
        ticketOrder.setOpenid(openid);
        ticketOrder.setName("ACEC参会票");
        ticketOrder.setPayAmount(payAmount);
        ticketOrder.setPayStatus(0);
        ticketOrder.setPayStatusName("待付款");
        ticketOrder.setPayType("微信");
        ticketOrder.setPayChannel("公众号支付");
        ticketOrder.setFrom(from);
        ticketOrderService.saveOrUpdate(ticketOrder);

        if (null == ticketOrder || ticketOrder.getId() <= 0)
            return R.fail("支付订单发起失败");

        // 发起微信公众号支付
        Map<String, String> map = Maps.newHashMap();
        map.put("openid", openid);
        map.put("OutTradeNo", ticketOrder.getOrderCode());
        map.put("body", ticketOrder.getName());
        map.put("fee", String.valueOf(ticketOrder.getPayAmount()));
        map.put("tradeType", EnumType.TradeType.WECHAT_JSAPI.getType());
        map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeCategory.NJ.getType()));
        // 获取统一下单后的参数
        R<Object> r = WxPayBusiness.Init().unifiedOrderBusiness(request, map, njAppId, njAppSecret, njMchId, njMchKey, notifyUrl);
        return r;
    }


    @ApiOperation(value = "通过手机号获取免费门票用户信息")
    @PostMapping(value = "/getTicketUserByUid")
    public R<Object> getTicketUserByUid(
            @ApiParam(value = "用户uid") @RequestParam(value = "uid") String uid
    ) {
        if (StringUtils.isBlank(uid))
            return R.fail("未传递用户uid");

        String year = String.valueOf(DateUtil.getYear());

        NjTicketUser user = ticketUserService.getByUid(uid, year);
        if (user != null) {
            if (user.getTicketType() == null || !user.getTicketType().equals(2))
                return R.fail("不是观展票用户");
            return R.ok(user);
        }
        return R.ok();
    }

    @ApiOperation(value = "导入抖音免费观展票用户")
    @PostMapping(value = "/importFeeTicketUser")
    public R<Object> importFeeTicketUser(
            @ApiParam(value = "抖音免费观展票用户") @RequestPart(value = "books") MultipartFile multipartFile,
            @ApiParam(value = "来源") @RequestParam(value = "source", required = false) String source
    ) throws Exception {
        List<TicketUserVO> voList = ExcelHandler.importExcel(multipartFile, TicketUserVO.class, null);
        if (CollectionUtils.isEmpty(voList))
            return R.fail("导入的数据为空");

        List<String> phoneList = voList.stream().filter(ticketUserVO -> StringUtils.isNotBlank(ticketUserVO.getPhone()))
                .map(TicketUserVO::getPhone).distinct().collect(Collectors.toList());

        if (phoneList.size() != voList.size())
            return R.fail("表格内的手机号重复或者缺失");

        String year = String.valueOf(DateUtil.getYear());

        List<String> exitsPhone = ticketUserService.listByPhoneAndYear(year, phoneList);
        if (CollectionUtils.isNotEmpty(exitsPhone))
            return R.fail("手机号重复了，" + StringUtils.join(exitsPhone, ","));

        List<NjTicketUser> newList = new ArrayList<>();

        // 添加书籍信息
        for (int i = 0; i < voList.size(); i++) {
            TicketUserVO user = voList.get(i);
            // 书名
            String phone = user.getPhone();
            if (StringUtils.isBlank(phone))
                return R.fail("未填写手机号, 第" + (i + 1) + "行");
            if (phone.length() != 11)
                return R.fail("手机号错误, 第" + (i + 1) + "行");
            // 用户姓名
            String name = user.getName();
            // 机构名
            String corpName = user.getCorpName();

            // 创建门店书籍实体
            NjTicketUser data = new NjTicketUser();
            data.setName(name);
            data.setCorpName(corpName);
            data.setPhone(phone);
            data.setUid(KitUtil.getUuid());
            data.setTicketType(2);
            data.setTicketTypeName("观展票");
            data.setUserType("观展人员");
            data.setGetStatus(1);
            data.setGetStatusName("已领票");
            data.setPermitStatus(0);
            data.setPermitStatusName("未领取");
            data.setPaymentStatus(0);
            data.setPaymentStatusName("未付款");
            data.setPermitNum(0);
            data.setYear(year);
            data.setSource(source);
            newList.add(data);
        }
        ticketUserService.saveBatch(newList);

        return R.fail(0, "保存数量：" + newList.size() + "，正在保存请稍后查询.");
    }

    @Deprecated
    @ApiOperation(value = "测试-发送成功预约观展门票用户")
    @PostMapping(value = "/acecSendTicketFeeTest", produces = "application/json; charset=UTF-8")
    public R<Object> acecSendTicketFeeTest(
            @ApiParam(value = "手机号") @RequestParam(value = "phone") String phone
    ) throws Exception {
        String year = String.valueOf(DateUtil.getYear());

        List<NjTicketUser> userList = ticketUserService.getByPhone(phone, year);
        if (CollectionUtils.isEmpty(userList))
            return R.fail("用户信息未查询到");
        NjTicketUser user = userList.get(0);
        String s = AliyunMessageUtils.acecSendTicketFee(accessKeyId, accessKeySecret, phone, user.getUid());

        return R.ok(s);
    }

    @Async
    @ApiOperation(value = "发送短信-成功预约观展门票用户")
    @PostMapping(value = "/acecSendTicketFee", produces = "application/json; charset=UTF-8")
    public R<Object> acecSendTicketFee(
            @ApiParam(value = "来源（抖音）") @RequestParam(value = "source") String source
    ) throws Exception {
        String year = String.valueOf(DateUtil.getYear());

        List<NjTicketUser> userList = ticketUserService.listByYearAndSource(year, source);
        if (CollectionUtils.isEmpty(userList))
            return R.fail("用户信息未查询到");

        // 异步发送短信
        msgTask.sendMsg(accessKeyId, accessKeySecret, userList);

        return R.ok();
    }

//    public static void main(String[] args) {
//        try {
//            String send = AliyunMessageUtils.acecSendVerifyCode("LTAI5t9qXosp1vM5bLYbmzt7", "zFq3lthPBatEYKOnBUvfuvSKttT40R", "13818924556", "1234");
//            System.out.println("send = " + send);
//        } catch (ClientException e) {
//            throw new RuntimeException(e);
//        }
//    }

}